diff --git a/ixgbe/Makefile b/src/Makefile
index 057b034..5b9092c 100644
--- a/ixgbe/Makefile
+++ b/ixgbe/Makefile
@@ -7,8 +7,8 @@ ifneq ($(KERNELRELEASE),)
 # Makefile for the Intel(R) 10GbE PCI Express Linux Network Driver
 #
 
-obj-$(CONFIG_IXGBE) += ixgbe.o
-define ixgbe-y
+obj-$(CONFIG_IXGBE) += ixgbe$(NETMAP_DRIVER_SUFFIX).o
+define ixgbe$(NETMAP_DRIVER_SUFFIX)-y
 	ixgbe_main.o
 	ixgbe_api.o
 	ixgbe_common.o
@@ -31,19 +31,19 @@ define ixgbe-y
 	ixgbe_devlink.o
 	ixgbe_fw_update.o
 endef
-ixgbe-y := $(strip ${ixgbe-y})
-
-ixgbe-${CONFIG_DCB} += ixgbe_dcb_nl.o
-ixgbe-${CONFIG_DEBUG_FS} += ixgbe_debugfs.o
-ixgbe-${CONFIG_FCOE:m=y} += ixgbe_fcoe.o
-ixgbe-$(CONFIG_PTP_1588_CLOCK:m=y) += ixgbe_ptp.o
-ixgbe-$(CONFIG_PTP_1588_CLOCK:m=y) += ixgbe_ptp_e600.o
-ixgbe-${CONFIG_SYSFS} += ixgbe_sysfs.o
+ixgbe$(NETMAP_DRIVER_SUFFIX)-y := $(strip ${ixgbe$(NETMAP_DRIVER_SUFFIX)-y})
+
+ixgbe$(NETMAP_DRIVER_SUFFIX)-${CONFIG_DCB} += ixgbe_dcb_nl.o
+ixgbe$(NETMAP_DRIVER_SUFFIX)-${CONFIG_DEBUG_FS} += ixgbe_debugfs.o
+ixgbe$(NETMAP_DRIVER_SUFFIX)-${CONFIG_FCOE:m=y} += ixgbe_fcoe.o
+ixgbe$(NETMAP_DRIVER_SUFFIX)-$(CONFIG_PTP_1588_CLOCK:m=y) += ixgbe_ptp.o
+ixgbe$(NETMAP_DRIVER_SUFFIX)-$(CONFIG_PTP_1588_CLOCK:m=y) += ixgbe_ptp_e600.o
+ixgbe$(NETMAP_DRIVER_SUFFIX)-${CONFIG_SYSFS} += ixgbe_sysfs.o
 # Use kcompat pldmfw.c if kernel does not provide CONFIG_PLDMFW
 ifndef CONFIG_PLDMFW
-ixgbe-y += kcompat_pldmfw.o
+ixgbe$(NETMAP_DRIVER_SUFFIX)-y += kcompat_pldmfw.o
 endif
-ixgbe-y += kcompat.o
+ixgbe$(NETMAP_DRIVER_SUFFIX)-y += kcompat.o
 else	# ifneq($(KERNELRELEASE),)
 # normal makefile
 
@@ -116,8 +116,10 @@ ccc: clean
 	@+$(call devkernelbuild,modules,coccicheck MODE=report))
 
 # Build manfiles
-manfile:
+manfile: ../$(DRIVER).$(MANSECTION)
 	@gzip -c ../${DRIVER}.${MANSECTION} > ${DRIVER}.${MANSECTION}.gz
+../$(DRIVER).$(MANSECTION):
+	touch $@
 # Clean the module subdirectories
 clean:
 	@+$(call devkernelbuild,clean)
diff --git a/ixgbe/ixgbe_main.c b/src/ixgbe_main.c
index e41b4a8..2fa2a6e 100644
--- a/ixgbe/ixgbe_main.c
+++ b/ixgbe/ixgbe_main.c
@@ -805,6 +805,23 @@ static void ixgbe_tx_timeout(struct net_device *netdev)
 	}
 }
 
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
+/*
+ * The #ifdef DEV_NETMAP / #endif blocks in this file are meant to
+ * be a reference on how to implement netmap support in a driver.
+ * Additional comments are in ixgbe_netmap_linux.h .
+ *
+ * The code is originally developed on FreeBSD and in the interest
+ * of maintainability we try to limit differences between the two systems.
+ *
+ * <ixgbe_netmap_linux.h> contains functions for netmap support
+ * that extend the standard driver.
+ * It also defines DEV_NETMAP so further conditional sections use
+ * that instead of CONFIG_NETMAP
+ */
+#include <ixgbe_netmap_linux.h>
+#endif
+
 /**
  * ixgbe_reset_pf_report - reset pf and print reset report
  * @tx_ring: tx ring number
@@ -980,6 +997,17 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
 	if (test_bit(__IXGBE_DOWN, adapter->state))
 		return true;
 
+#ifdef DEV_NETMAP
+	/*
+	 * In netmap mode, all the work is done in the context
+	 * of the client thread. Interrupt handlers only wake up
+	 * clients, which may be sleeping on individual rings
+	 * or on a global resource for all rings.
+	 */
+	if (netmap_tx_irq(adapter->netdev, tx_ring->queue_index) != NM_IRQ_PASS)
+		return true;
+#endif /* DEV_NETMAP */
+
 	tx_buffer = &tx_ring->tx_buffer_info[i];
 	tx_desc = IXGBE_TX_DESC(tx_ring, i);
 	i -= tx_ring->count;
@@ -2497,6 +2525,16 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
 	unsigned int xdp_xmit = 0;
 	struct xdp_buff xdp;
 
+#ifdef DEV_NETMAP
+	/*
+	 * 	 Same as the txeof routine: only wakeup clients on intr.
+	 */
+	int dummy, nm_irq;
+	nm_irq = netmap_rx_irq(rx_ring->netdev, rx_ring->queue_index, &dummy);
+	if (nm_irq != NM_IRQ_PASS)
+		return (nm_irq == NM_IRQ_RESCHED) ? budget : 1;
+#endif /* DEV_NETMAP */
+
 	xdp.data = NULL;
 	xdp.data_end = NULL;
 #ifdef HAVE_XDP_BUFF_RXQ
@@ -4587,6 +4625,10 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
 	memset(ring->tx_buffer_info, 0,
 	       sizeof(struct ixgbe_tx_buffer) * ring->count);
 
+#ifdef DEV_NETMAP
+	txdctl = ixgbe_netmap_configure_tx_ring(adapter, reg_idx, txdctl);
+#endif /* DEV_NETMAP */
+
 	/* enable queue */
 	IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), txdctl);
 
@@ -5280,6 +5322,12 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
 	IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
 
 	ixgbe_rx_desc_queue_enable(adapter, ring);
+
+#ifdef DEV_NETMAP
+	if (ixgbe_netmap_configure_rx_ring(adapter, reg_idx))
+		return;
+#endif /* DEV_NETMAP */
+
 #ifdef HAVE_AF_XDP_ZC_SUPPORT
 	if (ring->xsk_pool)
 		ixgbe_alloc_rx_buffers_zc(ring, ixgbe_desc_unused(ring));
@@ -15170,6 +15218,11 @@ no_info_string:
 		ixgbe_ptp_init_e600(adapter);
 
 #endif /* HAVE_PTP_1588_CLOCK && LINKVILLE_HW */
+
+#ifdef DEV_NETMAP
+	ixgbe_netmap_attach(adapter);
+#endif /* DEV_NETMAP */
+
 	return 0;
 
 err_devlink_register:
@@ -15259,6 +15312,11 @@ static void ixgbe_remove(struct pci_dev *pdev)
 		ixgbe_pf_fwlog_deinit(adapter);
 
 	netdev = adapter->netdev;
+
+#ifdef DEV_NETMAP
+	ixgbe_netmap_detach(adapter);
+#endif /* DEV_NETMAP */
+
 #ifdef HAVE_IXGBE_DEBUG_FS
 	ixgbe_dbg_adapter_exit(adapter);
 
